﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

using C1.Phone.Chart;
using System.Windows.Controls.Primitives;
using Microsoft.Phone.Shell;
using Microsoft.Phone.Controls;

namespace ControlExplorer.Controls.Chart
{
    public partial class PopupLabels : UserControl, IExposeApplicationBarItems, IExposePageOrientation
    {
        ApplicationBarIconButton btnStacked = new ApplicationBarIconButton(new Uri("Resources/AppBar/layers.png", UriKind.Relative));
        Dictionary<string, Popup> lbls = new Dictionary<string, Popup>();

        public PopupLabels()
        {
            InitializeComponent();
            
            btnStacked.Text = "Stacked";
            btnStacked.Click += btnStacked_Click;

            // hide all grid lines
            c1Chart1.View.AxisX.MajorGridStrokeThickness = 0;
            c1Chart1.View.AxisX.MinorGridStrokeThickness = 0;
            c1Chart1.View.AxisX.Scale = 0.6;
            c1Chart1.Actions.Add(new TranslateAction());
            ((System.ComponentModel.INotifyPropertyChanged)c1Chart1.View.AxisX).PropertyChanged += 
              (s,e) =>
              {
                if(e.PropertyName == "Value")
                  UpdateLabels();
              };

            // hide all tick marks
            c1Chart1.View.AxisX.MajorTickThickness = 0;
            c1Chart1.View.AxisX.MinorTickThickness = 0;
            c1Chart1.View.AxisY.MajorTickThickness = 0;
            c1Chart1.View.AxisY.MinorTickThickness = 0;

            // hide actual grid line
            c1Chart1.View.AxisY.AxisLine = new Line() { StrokeThickness = 0 };

            this.Unloaded += new RoutedEventHandler(PopupLabels_Unloaded);
        }

        void HideLabels()
        {
          foreach (var popup in lbls.Values)
          {
            popup.IsOpen = false;
          }
        }

        void UpdateLabels()
        {
          foreach (var popup in lbls.Values)
          {
            var child = popup.Child as FrameworkElement;
            var dp = child.DataContext as DataPoint;

            var pr = c1Chart1.View.PlotRect;
  
            var pt = c1Chart1.View.DataIndexToPoint(dp.SeriesIndex, dp.PointIndex);
            if (pt.X >= pr.Right || pt.X <= pr.Left)
              child.Visibility = System.Windows.Visibility.Collapsed;
            else
              child.Visibility = System.Windows.Visibility.Visible;

            popup.HorizontalOffset = pt.X - 0.5*child.Width;
            if (popup.HorizontalOffset < pr.Left)
              popup.HorizontalOffset = pr.Left;
            if (popup.HorizontalOffset + child.Width > pr.Right)
              popup.HorizontalOffset = pr.Right - child.Width;
            popup.UpdateLayout();
          }
        }

        void PopupLabels_Unloaded(object sender, RoutedEventArgs e)
        {
          HideLabels();
        }

        private void DataSeries_PlotElementLoaded(object sender, EventArgs e)
        {
            PlotElement pe = sender as PlotElement;
            if (pe != null)
            {
                pe.MouseLeftButtonUp += new MouseButtonEventHandler(pe_MouseLeftButtonUp);
                pe.Tap += new EventHandler<GestureEventArgs>(pe_Tap);
            }
        }

        void pe_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            PlotElement pe = sender as PlotElement;
            if (pe != null && IsPopup)
            {
                // initialize popup content
                // popup child must have explicit width set on UserControl!
              Popup popup = null;
              
              string key = "s" + pe.DataPoint.SeriesIndex + "p" + pe.DataPoint.PointIndex;
              if (lbls.Keys.Contains(key))
                popup = lbls[key];
              else
                lbls[key] = popup = new Popup();

                Interaction.PopupContent child = new Interaction.PopupContent();
                child.DataContext = pe.DataPoint;
                popup.Child = child;

                // declare local variables
                double y = e.GetPosition(c1Chart1).Y;
                double x = e.GetPosition(c1Chart1).X;
                double plotLeft = pe.PlotRect.Left;
                double plotTop = pe.PlotRect.Top;
                double plotBottom = pe.PlotRect.Bottom;
                double plotRight = pe.PlotRect.Right;
                double popupOffset = child.Width / 2;

                // set horizontal offset
                if (popupOffset > Math.Abs(x - plotLeft))
                {
                    // too far to the left
                    popup.HorizontalOffset = plotLeft;
                }
                else if (popupOffset > Math.Abs(x - plotRight))
                {
                    // too far to the right
                    popup.HorizontalOffset = plotRight - child.Width;
                }
                else
                {
                    popup.HorizontalOffset = e.GetPosition(c1Chart1).X - popupOffset;
                }


                // set vertical offset
                popup.VerticalOffset = e.GetPosition(LayoutRoot).Y - 50;
                if (popup.VerticalOffset < 0)
                  popup.VerticalOffset = 0;


                popup.IsOpen = true;
                popup.UpdateLayout();
            }
            IsPopup = false;
        }

        bool IsPopup = true;
        void pe_Tap(object sender, GestureEventArgs e)
        {
            IsPopup = true;
        }

        void btnStacked_Click(object sender, EventArgs e)
        {
            c1Chart1.ChartType = c1Chart1.ChartType == ChartType.Column? ChartType.ColumnStacked : ChartType.Column;
            HideLabels();
        }

        #region IExposeApplicationBarItems Members

        public IEnumerable<IApplicationBarMenuItem> ApplicationBarItems
        {
            get
            {
                yield return btnStacked;
            }
        }

        #endregion
        #region IExposePageOrientation Members

        public SupportedPageOrientation Orientation
        {
            get
            {
                return SupportedPageOrientation.Portrait;
            }
        }

        #endregion
    }
}
